#include <iostream>
#include <cassert>
#include "terminal512.h"
const int MANUAL=1;
const int AUTO=0;

Terminal::~Terminal(void)
{
    delete this->darsenas;
}

bool Terminal::AlgunoEnDarsena(void)const
{
    bool res=true;
    int cont=0;
    while(cont<this->cantdarsenas && res==true)
    {
        res=this->darsenas[cont].vacia();
        cont++;
    }

    return !res;
}



int Terminal::cantDarsenas() const
{
    return cantdarsenas;
}

bool Terminal::esperandoChofer() const
{
    return estaTrabado;
}

int Terminal::internosEnDarsena(int nroDarsena) const
{
    assert(nroDarsena<cantdarsenas);
    int n;
    n=darsenas[nroDarsena].tamano();
    return n;
}

IdInterno Terminal::internoEnPosicion(int nroDarsena, int posicion) const
{

    assert(nroDarsena>=0 && nroDarsena<cantdarsenas);
    assert(posicion>=0 && int(posicion)<int(darsenas[nroDarsena].tamano()));
    iterCola<colectivoConViajes> it;
    it.crearItcola(darsenas[nroDarsena]);
    int cont;
    cont=posicion+1;
    IdInterno res;
    while(cont!=0)
    {
        res=it.proximocola().Elcolectivo().ID();
        cont--;
    }
    return res;
}

bool Terminal::esInterno(IdInterno i)
{
    iterConj<colectivoConViajes> it;
    bool res;
    res=false;
    it.crearItc(ColectivosViajando.claves());
    while(it.tieneProximoc() && res==false)
    {
        res=it.proximoc().Elcolectivo().ID()==i;
    }
    int contaux;
    contaux=0;
    while(contaux<this->cantdarsenas && res==false)
    {
        iterCola<colectivoConViajes> it;
        it.crearItcola(darsenas[contaux]);

        while(it.tieneProximocola() && res==false)
        {
            res=it.proximocola().Elcolectivo().ID()==i;
        }
        contaux++;

    }

         return res;
}

IdChofer Terminal::quienManeja(IdInterno i) //const
{
    assert(esInterno(i));
    assert(viajando(i));
    iterConj<colectivoConViajes> it;
    it.crearItc(this->ColectivosViajando.claves());
    colectivoConViajes aux;
    bool resultado;
    resultado=false;
    while(resultado==false)
    {
       aux=it.proximoc();
       resultado=aux.Elcolectivo().ID()==i;
    }

   return ColectivosViajando.obtener(aux).ID();
}


bool Terminal::viajando(IdInterno i) const
{
    iterConj<colectivoConViajes> it;
    it.crearItc(this->ColectivosViajando.claves());
    bool res;
    res=false;
    while(it.tieneProximoc() && res==false)
    {
        res=it.proximoc().Elcolectivo().ID()==i;
    }

    return res;
}

bool Terminal::esChofer(IdChofer i) const
{
    conjAc<Chofer> jovenes(this->ChoferesEsperandoJovenes);
    bool resultado=false;
    while(resultado==false && jovenes.cardinal()>0)
    {
        resultado=jovenes.dameUno().ID()==i;
        jovenes.sinUno();

    }


    if (resultado==false)
    {
        conjAc<Chofer> viejos(this->ChoferesEsperandoViejos);
        while(resultado==false && viejos.cardinal()>0)
        {
             resultado=viejos.dameUno().ID()==i;
             viejos.sinUno();
        }
    }
    if (resultado==false)
    {

        iterConj<colectivoConViajes> it;
        colectivoConViajes aux;
        it.crearItc(this->ColectivosViajando.claves());
        while(it.tieneProximoc() && resultado==false)
        {
            aux=it.proximoc();
            resultado=this->ColectivosViajando.obtener(aux).ID()==i;
        }
    }
    return resultado;
}


Terminal::Terminal(int cantDarsenas, const ConjInterno &inter,  const ConjChofer &chof)
{
  assert(validaConstructor(cantDarsenas, inter, chof));

    this->cantdarsenas=cantDarsenas;
    int pibes;
    int viej;
    pibes=0;
    viej=0;
    iterConj<Chofer> it;
    it.crearItc(chof);
    this->estaTrabado=false;
   this->darsenas= new Cola <colectivoConViajes>[cantDarsenas];

    while(it.tieneProximoc())
    {
        if (it.proximoc().edad()<=40)
        {
            pibes++;
        }
        else
        {
            viej++;
        }
    }
    conjAc<Chofer> jov(pibes);
    conjAc<Chofer> oldie(viej);
    this->ChoferesEsperandoJovenes=jov;
    this->ChoferesEsperandoViejos=oldie;
    Chofer aux;
    it.crearItc(chof);
    while(it.tieneProximoc())
    {
        aux=it.proximoc();
        if (aux.edad()<=40)
        {
           this->ChoferesEsperandoJovenes.Ag(aux);
        }
        else
        {
            this->ChoferesEsperandoViejos.Ag(aux);
        }
    }

    iterConj<Interno> ite;
    ite.crearItc(inter);


    while(ite.tieneProximoc())
    {

       colectivoConViajes coleconviaj(0,ite.proximoc());
        this->darsenas[0].encolar(coleconviaj);
    }

  Cola<colectivoConViajes> sinnada;
    int cont;
    cont=1;
    while(cont<this->cantdarsenas)
    {
        this->darsenas[cont]=sinnada;
        cont++;
    }

}

Terminal& Terminal::llegaInterno(IdInterno i, int d)
{
    assert(this->esInterno(i));
    assert(this->viajando(i));
    assert(d>=0 && d<this->cantdarsenas);
    colectivoConViajes aux;
    iterConj<colectivoConViajes> it;

    it.crearItc(this->ColectivosViajando.claves());
    bool loencontre;
    loencontre=false;
    while(it.tieneProximoc() && loencontre==false)
    {
        aux=it.proximoc();
        loencontre=aux.Elcolectivo().ID()==i;
    }


    Chofer chof;
    chof=this->ColectivosViajando.obtener(aux);
    if (chof.edad()<=40)
    {
        this->ChoferesEsperandoJovenes.Ag(chof);
    }
    else
    {
        this->ChoferesEsperandoViejos.Ag(chof);
    }

    this->ColectivosViajando.borrar(aux);
    aux.hacerviaje();
    this->darsenas[d].encolar(aux);
    if (this->estaTrabado)
    {
      return (this->saleInterno());
    }
    else
    {return *this;}

}






const Chofer Terminal::elChofer(IdChofer i) const
{
    assert(this->esChofer(i));
    Chofer res;
    conjAc<Chofer> jovenes(this->ChoferesEsperandoJovenes);
    bool resultado=false;
    while(resultado==false && jovenes.cardinal()>0)
    {
        res=(jovenes.dameUno());
        resultado=res.ID()==i;
        jovenes.sinUno();

    }


    if (resultado==false)
    {
        conjAc<Chofer> viejos(this->ChoferesEsperandoViejos);
        while(resultado==false && viejos.cardinal()>0)
        {
             res=(viejos.dameUno());
             resultado=res.ID()==i;
             viejos.sinUno();
        }
    }
    if (resultado==false)
    {

        iterConj<colectivoConViajes> it;
        colectivoConViajes aux;
        it.crearItc(this->ColectivosViajando.claves());
        while(it.tieneProximoc() && resultado==false)
        {
            aux=it.proximoc();
            res=this->ColectivosViajando.obtener(aux);
            resultado=res.ID()==i;

        }
    }
   // cout<<res<<endl;
    //cout<<(*res)<<endl;;
    return (res);
}




const Interno Terminal::elInterno(IdInterno i) const
{
    colectivoConViajes p;
    iterConj<colectivoConViajes> it;
    bool res;
    res=false;
    it.crearItc(ColectivosViajando.claves());
    while(it.tieneProximoc() && res==false)
    {
        p=(it.proximoc());
        res=p.Elcolectivo().ID()==i;
    }
    int contaux;
    contaux=0;
    while(contaux<this->cantdarsenas && res==false)
    {
        iterCola<colectivoConViajes> it;
        it.crearItcola(darsenas[contaux]);

        while(it.tieneProximocola() && res==false)
        {
            p=(it.proximocola());
            res=p.Elcolectivo().ID()==i;
        }
        contaux++;

    }

        return p.Elcolectivo();
}

Terminal& Terminal::saleInterno()
{
    assert(this->AlgunoEnDarsena());
    assert(this->esperandoChofer()==false);

    colectivoConViajes MinManual;
    colectivoConViajes MinAuto;
    colectivoConViajes aux;
    int darsenaManual;
    darsenaManual=0;
    int darsenaAuto;
    darsenaAuto=0;
    int cantManual;
    cantManual=0;
    int cantAuto;
    cantAuto=0;
    int cont=0;
    bool vaciaManual;
    bool vaciaAuto;
    vaciaAuto=true;
    vaciaManual=true;
    bool yadespache=false;
    Chofer elquesale;
    while(cont<this->cantdarsenas)

     {
         if (darsenas[cont].vacia()==false)
         {
             aux=darsenas[cont].proximo();
             if (aux.Elcolectivo().transmision()==MANUAL)
                {
                    cantManual++;
                    if (aux.viajesHechos()<MinManual.viajesHechos() || vaciaManual)
                    {
                        MinManual=aux;
                        darsenaManual=cont;
                        vaciaManual=false;
                    }

                }

        else
        {
            cantAuto++;
            if (aux.viajesHechos()<MinAuto.viajesHechos() || vaciaAuto)
            {
                MinAuto=aux;
                darsenaAuto=cont;
                vaciaAuto=false;
            }

        }

         }
        cont++;
     }
     MinAuto.hacerviaje();
     MinManual.hacerviaje();
     this->estaTrabado=(this->ChoferesEsperandoJovenes.cardinal()+this->ChoferesEsperandoViejos.cardinal()==0) || (cantAuto>0 && cantManual==0 && this->ChoferesEsperandoJovenes.cardinal()==0)  || (cantAuto+cantManual==0);
     if (vaciaAuto==true && vaciaManual==false && this->estaTrabado==false)
     {
         this->darsenas[darsenaManual].desencolar();
         elquesale=this->ChoferesEsperandoJovenes.dameUno();
         this->ChoferesEsperandoJovenes.sinUno();
         yadespache=true;
         this->ColectivosViajando.definir(MinManual,elquesale);
     }


    if (vaciaAuto==false && vaciaManual==true && this->estaTrabado==false && yadespache==false)
     {
         this->darsenas[darsenaAuto].desencolar();
         elquesale=this->DameUnChofer();
         yadespache=true;
         this->ColectivosViajando.definir(MinAuto,elquesale);
     }

     if(this->estaTrabado==false && yadespache==false)
     {
         if((MinAuto.viajesHechos()>MinManual.viajesHechos()) ||(MinAuto.viajesHechos()==MinManual.viajesHechos() && MinAuto.Elcolectivo().ID()>MinManual.Elcolectivo().ID()))
         {
             this->darsenas[darsenaManual].desencolar();
             elquesale=this->ChoferesEsperandoJovenes.dameUno();
             this->ChoferesEsperandoJovenes.sinUno();
             yadespache=true;
             this->ColectivosViajando.definir(MinManual,elquesale);
         }
         else
         {
             this->darsenas[darsenaAuto].desencolar();
             elquesale=this->DameUnChofer();
             yadespache=true;
             this->ColectivosViajando.definir(MinAuto,elquesale);
         }
     }



    return *this;

}

Chofer Terminal::DameUnChofer(void)
 {
     bool entro=true;
     Chofer res;
     if (this->ChoferesEsperandoJovenes.cardinal()>0 && this->ChoferesEsperandoViejos.cardinal()>0)
     {
         if (this->ChoferesEsperandoJovenes.dameUno().ID()>this->ChoferesEsperandoViejos.dameUno().ID())
         {
             res=this->ChoferesEsperandoViejos.dameUno();
             this->ChoferesEsperandoViejos.sinUno();
             entro=false;
         }
         else
         {

             res=this->ChoferesEsperandoJovenes.dameUno();
             this->ChoferesEsperandoJovenes.sinUno();
             entro=false;
         }
     }
     if (entro && this->ChoferesEsperandoJovenes.cardinal()==0)
     {
         res=this->ChoferesEsperandoViejos.dameUno();
         this->ChoferesEsperandoViejos.sinUno();
         entro=false;
     }
     if (entro)
     {
         res=this->ChoferesEsperandoJovenes.dameUno();
         this->ChoferesEsperandoJovenes.sinUno();
     }
     return res;

}
int Terminal::cantViajesInterno(IdInterno i) const
{
    colectivoConViajes col;
    iterConj<colectivoConViajes> it;
    bool res;
    res=false;
    it.crearItc(ColectivosViajando.claves());
    while(it.tieneProximoc() && res==false)
    {
        col=it.proximoc();
        res=col.Elcolectivo().ID()==i;
    }
    int contaux;
    contaux=0;
    while(contaux<this->cantdarsenas && res==false)
    {
        iterCola<colectivoConViajes> it;
        it.crearItcola(darsenas[contaux]);

        while(it.tieneProximocola() && res==false)
        {
            col=it.proximocola();
            res=col.Elcolectivo().ID()==i;
        }
        contaux++;

    }

         return col.viajesHechos();
}


bool Terminal::validaConstructor(int cantDarsenas, const ConjInterno &inter, const ConjChofer &chof)
{
    bool res;
    res=cantDarsenas>0;
    res=res && chof.cantelem()>0 && inter.cantelem()>0;

    int automatico=0;
    int jovenes=0;

    iterConj<Chofer> it;
    it.crearItc(chof);
    while(it.tieneProximoc())
    {
        if (it.proximoc().edad()<=40)
        {
            jovenes++;
        }

    }
    iterConj<Interno> ite;
    ite.crearItc(inter);
     while(ite.tieneProximoc())
    {
        if (ite.proximoc().transmision()!=MANUAL)
        {
            automatico++;
        }

    }
    if (automatico>0)
    {
        res=res&&jovenes>0;
    }

    return res;
}
